package com.zeng.sys.authmd.servicemodule.service.serviceimpl;

import com.baomidou.mybatisplus.core.conditions.AbstractWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.zeng.nicecore.constant.IgnoreConstant;
import com.zeng.nicecore.util.BeanUtil;
import com.zeng.nicecore.util.IgnoreStringUtil;
import com.zeng.nicecore.validation.ValidGroup;
import com.zeng.nicecore.wrapper.QWrapper;
import com.zeng.sys.authmd.apimodule.service.*;
import com.zeng.sys.authmd.apimodule.service.com.zeng.sys.authmd.apimodule.constant.PermissionType;
import com.zeng.sys.authmd.apimodule.vo.*;
import com.zeng.sys.authmd.servicemodule.entity.Role;
import com.zeng.sys.authmd.servicemodule.entity.RolePermission;
import com.zeng.sys.authmd.servicemodule.entity.UserRole;
import com.zeng.sys.authmd.servicemodule.mapper.RoleMapper;
import com.zeng.sys.authmd.servicemodule.mapper.UserMapper;
import com.zeng.sys.authmd.servicemodule.entity.User;
import com.zeng.sys.authmd.servicemodule.mapper.UserRoleMapper;
import lombok.AllArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RequestBody;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

@Service
@Transactional
public class UserServiceImpl implements UserService {

    @Autowired
    UserMapper userMapper;

    @Autowired
    UserRoleMapper userRoleMapper;

    @Autowired
    RoleMapper roleMapper;

    @Autowired
    RoleService roleService;

    @Autowired
    RolePermissionService rolePermissionService;

    @Autowired
    UserRoleService userRoleService;

    @Autowired
    PermissionService permissionService;


    @Override
    public UserVo addOne(UserVo userVo) {
    User user = User.builder().build();
    BeanUtils.copyProperties(userVo, user, IgnoreStringUtil.ignoreExclude());
    int insert = userMapper.insert(user);
    return BeanUtil.beanToVo(user, userVo);
    }

    @Override
    public UserVo getOneByCode(String code) {

    User user = this.userMapper.selectById(code);
    UserVo userVo = BeanUtil.beanToVo(user, new UserVo());

    return userVo;
    }

    @Override
    public Integer update(UserVo userVo) {
    User user = BeanUtil.VoToBean(userVo,
    new User(),
    IgnoreStringUtil.ignoreExclude(IgnoreConstant.code.getValue()));
    return this.userMapper.updateById(user);
    }

    @Override
    public Integer delete(String code) {
        QueryWrapper queryWrapper = new QWrapper();
        queryWrapper.eq(UserRole.Fields.userCode, code);
        userRoleMapper.delete(queryWrapper);
    return this.userMapper.deleteById(code);
    }

    @Override
    public Integer batchDelete(List<String> codes) {
        QueryWrapper queryWrapper = new QWrapper();
        queryWrapper.in(UserRole.Fields.userCode, codes);
        userRoleMapper.delete(queryWrapper);
    return this.userMapper.deleteBatchIds(codes);
    }

    @Override
    public List<UserVo> findPage(Page page, UserVo userVo) {
        User user = BeanUtil.VoToBean(userVo, new User());
        this.userMapper.selectPage(page, this.getWrapper(userVo));
        List orders = page.getRecords();
        List<UserVo> userVos = new ArrayList<>();
        orders.forEach(e->{
            userVos.add(BeanUtil.beanToVo(e, new UserVo()));
        });
        page.setRecords(null);
        return userVos;
        }


    @Override
    public Integer count(UserVo userVo) {
        Integer integer = this.userMapper.selectCount(this.getWrapper(userVo));
        return integer;
    }

    @Override
    public UserVo getOneByUserAccount(String userAccount) {
        QueryWrapper<User> wrapper = new QWrapper<>();
        wrapper.eq(User.Fields.userAccount, userAccount);
        User user = userMapper.selectOne(wrapper);

        UserVo userVo = BeanUtil.beanToVo(user, new UserVo());
        return userVo;

    }

    @Override
    public UserVo addOneAndRole(UserVo userVo) {
        if (userVo == null) {
            return null;
        }
        UserVo addUser = addOne(userVo);

        if (userVo.getRoles() != null) {
            for (String roleCode : userVo.getRoles()) {
                userRoleMapper.insert(UserRole
                        .builder()
                        .userCode(addUser.getCode())
                        .roleCode(roleCode)
                        .build());
            }
        }


        return addUser;
    }

    @Override
    public UserVo detailUserAndRole(String code) {
        if (code == null) {
            return null;
        }
        HashMap<String, Object> map = new HashMap<>();
        map.put("user_code", code);
        List<UserRole> userRoles = userRoleMapper.selectByMap(map);
        List<String> roles = userRoles.stream().map(UserRole::getRoleCode).collect(Collectors.toList());
        UserVo oneByCode = this.getOneByCode(code);
        oneByCode.setRoles(roles);
        return oneByCode;
    }

    @Override
    public UserVo updateUserAndRole(@RequestBody @Validated(ValidGroup.Select.class) UserVo userVo) {
        this.update(userVo);
        QueryWrapper queryWrapper = new QWrapper();
        queryWrapper.eq(UserRole.Fields.userCode, userVo.getCode());
        userRoleMapper.delete(queryWrapper);
        if (userVo.getRoles() == null) {
            return userVo;
        }
        for (String role : userVo.getRoles()) {
            userRoleMapper.insert(UserRole.builder().userCode(userVo.getCode()).roleCode(role).build());
        }
        return userVo;
    }

    @Override
    public UserVo listUserApi(String userCode) {
        List<UserRoleVo> userRoleVos = userRoleService.listUserRoleByUserCode(userCode);
        List<String> roleCodes = userRoleVos.stream().map(UserRoleVo::getRoleCode).collect(Collectors.toList());
        List<RolePermissionVo> rolePermissionVos = rolePermissionService.listPermissionByRoleCodes(roleCodes);
        List<String> permissionCodes = rolePermissionVos.stream().map(RolePermissionVo::getPermissionCode).collect(Collectors.toList());
        List<PermissionVo> permissionVos = permissionService.listByCodesAndType(permissionCodes, PermissionType.API);
        Set<String> apis = permissionVos.stream().map(PermissionVo::getUrl).collect(Collectors.toSet());
        return UserVo.builder().apis(apis).build();
    }

    @Override
    public List<UserVo> findAll(UserVo userVo) {
        AbstractWrapper wrapper = this.getWrapper(userVo);
        List list = this.userMapper.selectList(wrapper);
        List<UserVo> userVos = new ArrayList<>();
        list.forEach(e->{
            userVos.add(BeanUtil.beanToVo(e, new UserVo()));
        });
        return list;
    }

    public AbstractWrapper getWrapper(UserVo userVo) {
        QueryWrapper<User> wrapper = new QWrapper<>();
        if (userVo != null) {
            if (StringUtils.isNotEmpty(userVo.getUserAccount())) {
                wrapper.like("userAccount", userVo.getUserAccount());
            }


        }
        return wrapper;
    }
}
